﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using ImageView.Shaders;

namespace ImageView
{
    /// <summary>
    /// Interaction logic for ViewImage.xaml
    /// </summary>
    public partial class ViewImage : UserControl
    {
        private EffectManager _em;
        private BitmapSource _current;
        private BitmapSource _next;
        private int i;
        private string[] _images;
        private DispatcherTimer _steptimer;
        private double clk;

        public ViewImage()
        {
            InitializeComponent();
            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            {
                _em = new EffectManager();
                i = 0;
                _steptimer = new DispatcherTimer();
                _steptimer.Tick += new EventHandler(_steptimer_Tick);
                _steptimer.Interval = TimeSpan.FromSeconds(1);
            }
        }

        void _steptimer_Tick(object sender, EventArgs e)
        {
            ++clk;
            if (clk >= TimeSllider.Value)
            {
                BtnNext_Click(sender, null);
                clk = 0;
            }
            TimeProgress.Value = clk;
            App.Taskbar.SetTaskbarProgressValue((int)clk, (int)TimeProgress.Maximum);
        }

        private void BtnTimer_Click(object sender, RoutedEventArgs e)
        {
            TimeProgress.Value = 0;
            TimeSllider.IsEnabled = !(bool)BtnTimer.IsChecked;
            _steptimer.IsEnabled = (bool)BtnTimer.IsChecked;
            if (!(bool)BtnTimer.IsChecked)
            {
                App.Taskbar.SetTaskbarProgessState(Microsoft.WindowsAPICodePack.Taskbar.TaskbarProgressBarState.NoProgress);
                TimeProgress.Value = 0;
            }
        }

        public string[] Images
        {
            get { return _images; }
            set
            {
                _images = value;
            }
        }

        public int StartIndex
        {
            get { return i; }
            set
            {
                if (i < 0 || i > Images.Length) throw new IndexOutOfRangeException();
                i = value;
                SetImage();
                UpdateStatusbar();
            }
        }

        private void DisposeUnused()
        {
            ImgCurrent.Source = null;
            if (_current != null) _current = null;
            if (_next != null) _next = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }

        private BitmapSource getImg(string path, bool small)
        {
            if (App.MainWin.IsVideo(path)) return App.Shell.GetThumbnail(path);

            BitmapImage ret = new BitmapImage();
            ret.BeginInit();
            ret.UriSource = new Uri(path);
            if (small)
            {
                ret.DecodePixelWidth = (int)(System.Windows.SystemParameters.PrimaryScreenWidth * 0.8);
            }
            ret.CacheOption = BitmapCacheOption.OnLoad;
            ret.EndInit();
            ret.Freeze();
            return ret;
        }

        private void AplyEffect()
        {
            TransitionEffect fx = _em.GetEffect();
            fx.Progress = 0;
            fx.OldImage = new ImageBrush(_current);
            fx.OldImage.Freeze();
            ImgCurrent.Effect = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            ImgCurrent.Effect = fx;

            DoubleAnimation da = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.5)), FillBehavior.HoldEnd);
            da.AccelerationRatio = 0.5;
            da.DecelerationRatio = 0.5;
            da.Completed += new EventHandler(da_Completed);
            fx.BeginAnimation(TransitionEffect.ProgressProperty, da);
        }

        private void da_Completed(object sender, EventArgs e)
        {
            LockButtons(false);
            UpdateStatusbar();
        }

        private void LockButtons(bool lockstate)
        {
            this.BtnNext.IsEnabled = !lockstate;
            this.BtnPrev.IsEnabled = !lockstate;
        }

        private void UpdateStatusbar()
        {
            ImgCounter.Text = _images.Length.ToString() + " / " + i.ToString();
            ImgFilename.Text = _images[i];
        }

        private void SetRotation(string file)
        {
            int rot = App.Shell.GetExifRotationInfo(file);
            ImgRot.Angle = 0;
            ImgScale.ScaleX = 1;
            ImgScale.ScaleY = 1;
            switch (rot)
            {
                case 2:
                    ImgScale.ScaleY = -1;
                    break;
                case 3:
                    ImgRot.Angle = -180;
                    break;
                case 4:
                    ImgScale.ScaleX = -1;
                    break;
                case 5:
                    ImgRot.Angle = 90;
                    ImgScale.ScaleY = -1;
                    break;
                case 6:
                    ImgRot.Angle = 90;
                    break;
                case 7:
                    ImgRot.Angle = -90;
                    ImgScale.ScaleY = -1;
                    break;
                case 8:
                    ImgRot.Angle = -90;
                    break;
            }
        }

        private void TransPres_TransitionCompleted(object sender, EventArgs e)
        {
            if (!(bool)FullView.IsChecked)
            {
                ImgFull.ClearImage();
                ImgFull.Opacity = 0;
            }
        }

        private void SetImage()
        {

            DisposeUnused();

            _current = getImg(Images[i], true);
            _next = getImg(Images[i], true);
            AplyEffect();
            ImgCurrent.Source = _next;
            SetRotation(Images[i]);
        }

        private void BtnNext_Click(object sender, RoutedEventArgs e)
        {
            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            {
                int next = i + 1;
                if (i + 1 > Images.Length -1) next = 0;
                LockButtons(true);

                DisposeUnused();
                if ((bool)FullView.IsChecked)
                {
                    TransPres.ApplyTransition(ImgFull, ImgCurrent);
                    FullView.IsChecked = false;
                }

                _current = getImg(Images[i], true);
                _next = getImg(Images[next], true);
                AplyEffect();
                ImgCurrent.Source = _next;
                SetRotation(Images[next]);
                ++i;
                if (i > Images.Length -1) i = 0;
            }
        }

        private void BtnPrev_Click(object sender, RoutedEventArgs e)
        {
            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            {
                int next = i - 1;
                if (i - 1 < 0) next = Images.Length - 1;
                LockButtons(true);

                DisposeUnused();
                if ((bool)FullView.IsChecked)
                {
                    TransPres.ApplyTransition(ImgFull, ImgCurrent);
                    FullView.IsChecked = false;
                }

                _current = getImg(Images[i], true);
                _next = getImg(Images[next], true);
                AplyEffect();
                ImgCurrent.Source = _next;
                SetRotation(Images[next]);
                --i;
                if (i < 0) i = Images.Length - 1;
            }
        }

        private void FullView_Click(object sender, RoutedEventArgs e)
        {
            if ((bool)FullView.IsChecked)
            {
                ImgFull.LoadImage(Images[i]);
                ImgFull.Opacity = 1;
                ImgFull.RotAngle = ImgRot.Angle;
                ImgFull.Scale = new Point(ImgScale.ScaleX, ImgScale.ScaleY);
                TransPres.ApplyTransition(ImgCurrent, ImgFull);
            }
            else TransPres.ApplyTransition(ImgFull, ImgCurrent);
        }

        private void RotCw_Click(object sender, RoutedEventArgs e)
        {
            if (ImgFull.Opacity == 1) ImgFull.Rotate90Cw();
            else ImgRot.Angle += 90;
        }

        private void RotCCw_Click(object sender, RoutedEventArgs e)
        {
            if (ImgFull.Opacity == 1) ImgFull.Rotate90CCw();
            else ImgRot.Angle -= 90;
        }

        private void FlipY_Click(object sender, RoutedEventArgs e)
        {
            if (ImgFull.Opacity == 1) ImgFull.FlipY();
            else ImgScale.ScaleY *= -1;
        }

        private void FlipX_Click(object sender, RoutedEventArgs e)
        {
            if (ImgFull.Opacity == 1) ImgFull.FlipX();
            else ImgScale.ScaleX *= -1;
        }
    }
}
